<?php

/**
 * 默认报告错误
 */
error_reporting(E_ALL ^ E_NOTICE);
ini_set('display_errors', '1');

/**
 * 定义框架版本
 */
const  VERSION = '1.0.0';

/**
 * 最低PHP版本要求
 */
const PHP_REQUIRED = '5.3.8';

/**
 * 加载必要类
 */
use variant\core\Kernel;
use variant\core\Exceptions;
use variant\core\Config;
use variant\core\Route;

/**
 * 定义常量
 */
if (!defined('DS')) define('DS', DIRECTORY_SEPARATOR);
if (!defined('BASE_PATH')) define('BASE_PATH', dirname(__DIR__) . DS);
if (!defined('SELF')) define('SELF', $_SERVER['PHP_SELF']);
if (!defined('VAT_PATH')) define('VAT_PATH', __DIR__ . DS);
if (!defined('ROOT_URL')) define('ROOT_URL', rtrim(dirname($_SERVER["SCRIPT_NAME"]), '\\/') . '/');
if (!defined('PUBLIC_URL')) define('PUBLIC_URL', ROOT_URL . 'public/');
if (!defined('ROOT_SCRIPT')) define('ROOT_SCRIPT', rtrim($_SERVER["SCRIPT_NAME"], '\\/') . '/');
if (!defined('APP_PATH')) define('APP_PATH', BASE_PATH . 'app' . DS);
if (!defined('DATA_PATH')) define('DATA_PATH', BASE_PATH . 'data' . DS);
if (!defined('IS_GET')) define('IS_GET', $_SERVER['REQUEST_METHOD'] == 'GET' ? true : false);
if (!defined('IS_POST')) define('IS_POST', $_SERVER['REQUEST_METHOD'] == 'POST' ? true : false);
if (!defined('IS_AJAX')) define('IS_AJAX', ((isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')) ? true : false);
if (!defined('IS_PJAX')) define('IS_PJAX', (array_key_exists('HTTP_X_PJAX', $_SERVER) && $_SERVER['HTTP_X_PJAX']) ? true : false);

/**
 * 启动框架
 */
function bootstrap() {
    step_env();
    step_loader();
    step_config();
    step_exceptions();
    step_function();
    step_route();
    //启动应用
    debug_log('bootstrap');
    step_start();
}

/**
 * 设置环境
 */
function step_env() {
    if (!isset($_SERVER['HTTP_REFERER'])) {
        $_SERVER['HTTP_REFERER'] = '';
    }
    if (!isset($_SERVER['SERVER_PROTOCOL'])
        || ($_SERVER['SERVER_PROTOCOL'] != 'HTTP/1.0' && $_SERVER['SERVER_PROTOCOL'] != 'HTTP/1.1')
    ) {
        $_SERVER['SERVER_PROTOCOL'] = 'HTTP/1.0';
    }
    if (isset($_SERVER['HTTP_HOST'])) {
        $_SERVER['HTTP_HOST'] = strtolower($_SERVER['HTTP_HOST']);
    } else {
        $_SERVER['HTTP_HOST'] = '';
    }
    if (version_compare(PHP_VERSION, PHP_REQUIRED, '<')) {
        header($_SERVER['SERVER_PROTOCOL'] . ' 500 PHP_VERSION');
        exit;
    }
    //设置当前URL
    if (isset($_SERVER['REQUEST_URI'])) {
        $uri = $_SERVER['REQUEST_URI'];
    } else {
        if (isset($_SERVER['argv'])) {
            $uri = $_SERVER['PHP_SELF'] . '?' . $_SERVER['argv'][0];
        } else {
            $uri = $_SERVER['PHP_SELF'] . '?' . $_SERVER['QUERY_STRING'];
        }
    }
    if (!defined('SELF_URL')) define('SELF_URL', $uri);
    //还原请求转义
    if (get_magic_quotes_gpc()) {
        $_POST = _stripslashes_deep($_POST);
        $_GET = _stripslashes_deep($_GET);
        $_COOKIE = _stripslashes_deep($_COOKIE);
    }
    //设置session
    ini_set('session.use_cookies', '1');
    ini_set('session.use_only_cookies', '1');
    ini_set('session.use_trans_sid', '0');
    ini_set('session.cache_limiter', '');
    //开始计时
    timer_start();
}


/**
 * 加载公共函数库
 */
function step_function() {
    require_once VAT_PATH . 'core/Common.php';
}

/**
 * 自动注册
 */
function step_loader() {
    spl_autoload_register('_class_loader');
}

/**
 * 错误接管
 */
function step_exceptions() {
    new Exceptions();
}

/**
 * 配置加载
 */
function step_config() {
    Config::init();
    Config::load(DATA_PATH . '/config/global.php');
}

/**
 * 路由处理
 */
function step_route() {
    Route::init(Config::get('ROUTE.REWRITE_ON'));

}

/**
 * 启动APP模式
 */
function step_start() {
    date_default_timezone_set(config('SYSTEM.TIMEZONE'));
    Kernel::run();
}

/**
 * 还原转义
 */
function _stripslashes_deep($value) {
    $value = is_array($value) ? array_map('_stripslashes_deep', $value) : (isset($value) ? stripslashes($value) : null);
    return $value;
}

/**
 * 加载类
 */
function _class_loader($class) {
    static $fileList = array();
    $class = ltrim($class, '\\');
    if (($pos = strrpos($class, '\\')) === false) {
        return false;
    }
    $namespace = substr($class, 0, $pos);
    $className = substr($class, $pos + 1);
    $namespace = str_replace('\\', DS, $namespace);
    $fileDir = BASE_PATH . $namespace . DS;
    $classFile = $fileDir . $className . '.php';
    if (!isset($fileList[$classFile])) {
        if (!is_file($classFile)) {
            return false;
        }
        $fileList[$classFile] = $classFile;
        require_once $classFile;
    }
    return true;
}

/**
 * 计时器
 */
function timer_start($name = 'default') {
    global $timers;
    $timers[$name]['start'] = microtime(true);
    $timers[$name]['count'] = isset($timers[$name]['count']) ? ++$timers[$name]['count'] : 1;
}

/**
 * 读取计时器
 */
function timer_read($name = 'default') {
    global $timers;
    if (isset($timers[$name]['start'])) {
        $stop = microtime(true);
        $diff = round(($stop - $timers[$name]['start']) * 1000, 2);
        if (isset($timers[$name]['time'])) {
            $diff += $timers[$name]['time'];
        }
        return $diff;
    }
    return $timers[$name]['time'];
}

/**
 * 停止计时器
 */
function timer_stop($name = 'default') {
    global $timers;
    if (isset($timers[$name]['start'])) {
        $stop = microtime(true);
        $diff = round(($stop - $timers[$name]['start']) * 1000, 2);
        if (isset($timers[$name]['time'])) {
            $timers[$name]['time'] += $diff;
        } else {
            $timers[$name]['time'] = $diff;
        }
        unset($timers[$name]['start']);
    }
    return $timers[$name];
}

/**
 * 设置调试记录
 */
function debug_log($log = '', $name = 'Debug') {
    if (!Config::get('EXCEPTIONS.DEBUG_LOG')) {
        return array();
    }
    static $logArray;
    if ($log) {
        $logArray[$name][] = array('log' => $log, 'time' => timer_read());
    }
    return $logArray;
}

/**
 * 输出内部错误
 */
function debug_echo($content) {
    throw new \Exception($content, 500);
}

/**
 * 配置方法
 * @param  string $key 配置项
 * @param  mixed $value 配置值
 * @return array
 */
function config($key = NULL, $value = NULL) {
    if (func_num_args() <= 1) {
        return Config::get($key);
    } else {
        return Config::set($key, $value);
    }
}

/**
 * 日志记录
 */
function logger() {
    return new \variant\core\Logger();
}